﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Aga.Controls.Tree;
using System.Collections;
using Aga.Controls.Tree.NodeControls;
using System.Collections.ObjectModel;

using OpenMetaverse;
namespace InventoryViewer
{
    //public class InventoryDirectorySelector
    //{
    //    // Fields
    //    private Form form = new Form();
    //    private InventoryTreeView treeView;

    //    // Methods
    //    public InventoryDirectorySelector(InventoryManager manager, Inventory inventory, InventoryNode root)
    //    {
    //        this.form.FormBorderStyle = FormBorderStyle.FixedDialog;
    //        this.treeView = new InventoryTreeView();
    //        this.treeView.Model = new InventoryTreeModel(manager, inventory, root, new InventoryType[0]);
    //        this.treeView.SelectionMode = TreeSelectionMode.Single;
    //        this.form.Controls.Add(this.treeView);
    //        Button ok = new Button();
    //        ok.Text = "Select";
    //        this.form.AcceptButton = ok;
    //        this.form.Controls.Add(ok);
    //        Button cancel = new Button();
    //        cancel.Text = "Cancel";
    //        this.form.CancelButton = cancel;
    //        this.form.Controls.Add(cancel);
    //    }

    //    public InventoryFolder ShowSelector()
    //    {
    //        if (this.form.ShowDialog() == DialogResult.OK)
    //        {
    //            return (this.treeView.SelectedInventory[0] as InventoryFolder);
    //        }
    //        return null;
    //    }
    //}

    //public class InventoryTreeModel : ITreeModel
    //{
    //    // Fields
    //    private Dictionary<InventoryType, object> DisplayedTypes;
    //    private Inventory Inventory;
    //    private InventoryNode InventoryRoot;
    //    private InventoryManager Manager;
    //    private Dictionary<InventoryNode, Node> ReverseMap;
    //    private Dictionary<InventoryFolder, object> DownloadedFolders;

    //    // Events
    //    public event EventHandler<TreeModelEventArgs> NodesChanged;

    //    public event EventHandler<TreeModelEventArgs> NodesInserted;

    //    public event EventHandler<TreeModelEventArgs> NodesRemoved;

    //    public event EventHandler<TreePathEventArgs> StructureChanged;
    //    // Methods
    //    public InventoryTreeModel(InventoryManager manager, Inventory inventory, InventoryNode root)
    //        : this(manager, inventory, root, (InventoryType[])Enum.GetValues(typeof(InventoryType)))
    //    {
    //    }

    //    public InventoryTreeModel(InventoryManager manager, Inventory inventory, InventoryNode root, InventoryType[] displayedTypes)
    //    {
    //        this.DisplayedTypes = new Dictionary<InventoryType, object>();
    //        this.DownloadedFolders = new Dictionary<InventoryFolder, object>();
    //        this.Manager = manager;
    //        this.InventoryRoot = root;
    //        this.Inventory = inventory;
    //        this.Inventory.OnInventoryObjectRemoved += new Inventory.InventoryObjectRemoved(this.Inventory_OnInventoryRemoved);
    //        inventory.OnInventoryObjectUpdated += new Inventory.InventoryObjectUpdated(this.inventory_OnInventoryUpdated);
    //        this.Inventory.OnInventoryObjectAdded += new Inventory.InventoryObjectAdded(this.Inventory_OnInventoryAdded);
    //        //this.NodeMap = new Dictionary<Node, InventoryNode>();
    //        this.ReverseMap = new Dictionary<InventoryNode, Node>();
    //        Node rootNode = new Node("My Inventory");
    //        rootNode.Tag = this.InventoryRoot.Data;
    //        //this.NodeMap.Add(rootNode, this.InventoryRoot);
    //        this.ReverseMap.Add(this.InventoryRoot, rootNode);
    //        this.DisplayedTypes = new Dictionary<InventoryType, object>(displayedTypes.Length);
    //        foreach (InventoryType type in displayedTypes)
    //        {
    //            this.DisplayedTypes[type] = null;
    //        }
    //    }

    //    public IEnumerable GetChildren(TreePath treePath)
    //    {
    //        List<Node> children = new List<Node>();
    //        if (treePath.IsEmpty())
    //        {
    //            children.Add(this.ReverseMap[this.InventoryRoot]);
    //            return children;
    //        }
    //        Node lastNode = treePath.LastNode as Node;
    //        InventoryBase invBase = lastNode.Tag as InventoryBase;
    //        InventoryNode invNode = Inventory.GetNodeFor(invBase.UUID);//this.NodeMap[treePath.LastNode as Node];
    //        if (invNode.Data is InventoryFolder)
    //        {
    //            Console.WriteLine("Requesting {0}'s ({1}) contents...", invNode.Data.Name, invNode.Data.UUID);
    //            Manager.RequestFolderContents(invNode.Data.UUID, Inventory.Owner, true, true, InventorySortOrder.ByName);
    //            foreach (InventoryNode child in invNode.Nodes.Values)
    //            {
    //                if ((child.Data is InventoryItem) && !this.DisplayedTypes.ContainsKey((child.Data as InventoryItem).InventoryType))
    //                {
    //                    continue;
    //                }
    //                if (!this.ReverseMap.ContainsKey(child))
    //                {
    //                    Node treeChild = new Node(child.Data.Name);
    //                    treeChild.Tag = child.Data;
    //                    this.ReverseMap.Add(child, treeChild);
    //                    //this.NodeMap.Add(treeChild, child);
    //                    Node parent = this.ReverseMap[child.Parent];
    //                    parent.Nodes.Add(treeChild);
    //                }
    //                children.Add(this.ReverseMap[child]);
    //            }
    //        }
    //        return children;
    //    }

    //    private TreePath GetPath(Node node)
    //    {
    //        if (node == null)
    //        {
    //            return TreePath.Empty;
    //        }
    //        Stack<object> stack = new Stack<object>();
    //        while (node != null)
    //        {
    //            stack.Push(node);
    //            node = node.Parent;
    //        }
    //        return new TreePath(stack.ToArray());
    //    }

    //    [Obsolete]
    //    private void InitializeModel()
    //    {
    //        //this.NodeMap = new Dictionary<Node, InventoryNode>();
    //        this.ReverseMap = new Dictionary<InventoryNode, Node>();
    //        Node rootNode = new Node("My Inventory");
    //        rootNode.Tag = this.InventoryRoot.Data;
    //        //this.NodeMap.Add(rootNode, this.InventoryRoot);
    //        this.ReverseMap.Add(this.InventoryRoot, rootNode);
    //        this.PopulateNode(this.InventoryRoot, rootNode);
    //    }

    //    private void Inventory_OnInventoryAdded(InventoryBase obj)
    //    {
    //        Node node = new Node(obj.Name);
    //        node.Parent = this.NodeForUUID(obj.ParentUUID);
    //        node.Tag = obj;
    //        InventoryNode invNode = Inventory.GetNodeFor(obj.UUID);
    //        this.ReverseMap.Add(invNode, node);
    //        //this.NodeMap.Add(node, invNode);
    //        Console.WriteLine("Added {0}", obj.Name);
    //        if (this.NodesInserted != null)
    //        {
    //            this.NodesInserted(this, new TreeModelEventArgs(this.GetPath(node.Parent), new int[] { 0 }, new object[] { node }));
    //        }
    //    }

    //    private void Inventory_OnInventoryRemoved(InventoryBase obj)
    //    {
    //        Node node = this.NodeForUUID(obj.UUID);
    //        if (node != null)
    //        {
    //            InventoryNode invNode = Inventory.GetNodeFor(obj.UUID);// this.NodeMap[node];
    //            //this.NodeMap.Remove(node);
    //            this.ReverseMap.Remove(invNode);
    //            if (this.NodesRemoved != null)
    //            {
    //                this.NodesRemoved(this, new TreeModelEventArgs(this.GetPath(node.Parent), new object[] { node }));
    //            }
    //        }
    //    }

    //    private void inventory_OnInventoryUpdated(InventoryBase oldObject, InventoryBase newObject)
    //    {
    //        Console.WriteLine("OnInventoryUpdated({0}, {1})",
    //            oldObject == null ? "null" : oldObject.Name,
    //            newObject == null ? "null" : newObject.Name);
    //        Node node = NodeForUUID(oldObject.UUID);
    //        if (NodeForUUID(oldObject.UUID) == null)
    //        {
    //            // It was in the inventory store before, but we didn't know about it:
    //            this.Inventory_OnInventoryAdded(newObject);
    //        }
    //        else
    //        {
    //            node.Text = newObject.Name;
    //            node.Tag = newObject;
    //            if (newObject.ParentUUID != oldObject.ParentUUID)
    //            {
    //                this.Inventory_OnInventoryRemoved(oldObject);
    //                this.Inventory_OnInventoryAdded(newObject);
    //            }
    //            else if (this.NodesChanged != null)
    //            {
    //                this.NodesChanged(this, new TreeModelEventArgs(this.GetPath(node.Parent), new object[] { node }));
    //            }
    //        }
    //    }

    //    public bool IsLeaf(TreePath treePath)
    //    {
    //        return !(((Node)treePath.LastNode).Tag is InventoryFolder);
    //    }

    //    private Node NodeForUUID(LLUUID uuid)
    //    {
    //        InventoryNode invNode = Inventory.GetNodeFor(uuid);
    //        Node node;
    //        if (!ReverseMap.TryGetValue(invNode, out node))
    //        {
    //            node = new Node(invNode.Data.Name);
    //            node.Tag = invNode.Data;
    //            ReverseMap.Add(invNode, node);
    //        }
    //        return node;
    //    }

    //    [Obsolete]
    //    private void PopulateNode(InventoryNode invParent, Node treeParent)
    //    {
    //        foreach (InventoryNode invChild in invParent.Nodes.Values)
    //        {
    //            Node treeChild = new Node(invChild.Data.Name);
    //            treeChild.Tag = invChild.Data;
    //            //this.NodeMap.Add(treeChild, invChild);
    //            this.ReverseMap.Add(invChild, treeChild);
    //            treeParent.Nodes.Add(treeChild);
    //            if (invChild.Nodes.Count > 0)
    //            {
    //                this.PopulateNode(invChild, treeChild);
    //            }
    //        }
    //    }
    //}



    //public class InventoryTreeView : TreeViewAdv
    //{
    //    // Fields
    //    public ContextMenuStrip FolderContextMenu;
    //    public ContextMenuStrip GeneralContextMenu;
    //    public ContextMenuStrip ItemContextMenu;
    //    public InventoryBase[] SelectedInventory;

    //    // Events
    //    public event EventHandler SelectionChanged;

    //    // Methods
    //    public InventoryTreeView()
    //    {
    //        base.LoadOnDemand = true;
    //        base.SelectionMode = TreeSelectionMode.Multi;
    //        NodeTextBox textBox = new NodeTextBox();
    //        textBox.DataPropertyName = "Text";
    //        textBox.Parent = this;
    //        textBox.EditEnabled = false;
    //        base.NodeControls.Add(textBox);
    //        base.SelectionChanged += new EventHandler(this.InventoryTreeView_SelectionChanged);
    //    }

    //    private void InventoryTreeView_SelectionChanged(object sender, EventArgs e)
    //    {
    //        ITreeModel model = base.Model;
    //        this.SelectedInventory = new InventoryBase[base.SelectedNodes.Count];
    //        ReadOnlyCollection<TreeNodeAdv> selectedNodes = base.SelectedNodes;
    //        int index = 0;
    //        bool folders = false;
    //        bool items = false;
    //        foreach (TreeNodeAdv node in selectedNodes)
    //        {
    //            Node innerNode = node.Tag as Node;
    //            this.SelectedInventory[index] = innerNode.Tag as InventoryBase;
    //            folders |= this.SelectedInventory[index] is InventoryFolder;
    //            items |= this.SelectedInventory[index] is InventoryItem;
    //            index++;
    //        }
    //        if (this.SelectionChanged != null)
    //        {
    //            this.SelectionChanged(this, e);
    //        }
    //        if (folders && !items)
    //        {
    //            base.BeginInvoke(new ContextMenuStripFunc(this.SetContextMenuStrip), new object[] { this.FolderContextMenu });
    //        }
    //        else if (items && !folders)
    //        {
    //            base.BeginInvoke(new ContextMenuStripFunc(this.SetContextMenuStrip), new object[] { this.ItemContextMenu });
    //        }
    //        else
    //        {
    //            base.BeginInvoke(new ContextMenuStripFunc(this.SetContextMenuStrip), new object[] { this.GeneralContextMenu });
    //        }
    //    }

    //    public void SetContextMenuStrip(ContextMenuStrip strip)
    //    {
    //        this.ContextMenuStrip = strip;
    //    }

    //    // Nested Types
    //    public delegate void ContextMenuStripFunc(ContextMenuStrip bar);
    //}

    #region Model
    public class ViewableInventory : Inventory, ITreeModel
    {
        private InventoryManager Manager;
        public ViewableInventory(InventoryManager manager)
            : base (manager)
        {
            Manager = manager;
            OnInventoryManaged += new InventoryManaged(ViewableInventory_OnInventoryManaged);
        }

        void ViewableInventory_OnInventoryManaged(Inventory inventory, InventoryBase ibase)
        {
            if (ibase is ViewableFolder)
            {
                ViewableFolder folder = ibase as ViewableFolder;

                if (NodesInserted != null)
                {
                    NodesInserted(this, new TreeModelEventArgs(PathTo(folder.Node.Parent), new int[] { -1 }, new object[] { folder.Node }));
                }
            }
            else
            {
                ViewableItem item = ibase as ViewableItem;

                if (NodesInserted != null)
                {
                    NodesInserted(this, new TreeModelEventArgs(PathTo(item.Node.Parent), new int[] { -1 }, new object[] { item.Node }));
                }
            }
        }

        protected override InventoryFolder WrapFolderData(FolderData data)
        {
            ViewableFolder folder = new ViewableFolder(Manager, this, data);
            return folder;
        }

        protected override InventoryItem WrapItemData(ItemData data)
        {
            ViewableItem item = new ViewableItem(Manager, this, data);
            return item;
        }

        public override void Unmanage(InventoryBase item)
        {
            base.Unmanage(item);
            Node node = null;

            if (item is ViewableItem)
                node = (item as ViewableItem).Node;
            else 
                node = (item as ViewableFolder).Node;

            if (NodesRemoved != null)
            {
                NodesRemoved(this, new TreeModelEventArgs(PathTo(node.Parent), new object[] { node }));
            }
        }

        private TreePath PathTo(Node node)
        {
            if (node == null)
                return TreePath.Empty;

            Stack<object> stack = new Stack<object>();
            while (node != null)
            {
                stack.Push(node);
                node = node.Parent;
            }
            return new TreePath(stack.ToArray());
        }

        public void NotifyNodeChanged(Node node)
        {
            if (NodesChanged != null)
            {
                NodesChanged(this, new TreeModelEventArgs(PathTo(node.Parent), new object[] {node}));
            }
        }

        public void NotifyParentChange(Node oldParent, Node newParent, Node child)
        {
            if (NodesRemoved != null)
            {
                NodesRemoved(this, new TreeModelEventArgs(PathTo(oldParent), new object[] { child }));
            }
            if (NodesInserted != null)
            {
                NodesInserted(this, new TreeModelEventArgs(PathTo(newParent), new int[] { 0 }, new object[] { child }));
            }
        }

        #region ITreeModel Members

        public IEnumerable GetChildren(TreePath treePath)
        {
            if (treePath.IsEmpty())
            {
                yield return (RootFolder as ViewableFolder).Node;
                yield break;
            }

            Node last = treePath.LastNode as Node;
            if (last.Tag is ViewableFolder)
            {
                ViewableFolder folder = last.Tag as ViewableFolder;
                if (folder.IsStale)
                    folder.RequestContents(InventorySortOrder.ByDate);

                foreach (InventoryBase ib in folder)
                {
                    if (ib is ViewableFolder)
                        yield return (ib as ViewableFolder).Node;
                    else
                        yield return (ib as ViewableItem).Node;
                }
            }
            else
            {
                yield break;
            }
        }

        public bool IsLeaf(TreePath treePath)
        {
            Node last = treePath.LastNode as Node;
            return last.Tag is InventoryItem;
        }

        public event EventHandler<TreeModelEventArgs> NodesChanged;

        public event EventHandler<TreeModelEventArgs> NodesInserted;

        public event EventHandler<TreeModelEventArgs> NodesRemoved;

        public event EventHandler<TreePathEventArgs> StructureChanged;

        #endregion
    }

    public class ViewableItem : InventoryItem
    {
        public Node Node;
        private ViewableInventory Inventory;
        public ViewableItem(InventoryManager manager, ViewableInventory inv, ItemData data)
            : base (manager, inv, data)
        {
            Inventory = inv;
            Node = new Node(this.Name);
            Node.Tag = this;

            if (Parent != null)
            {
                Node.Parent = (Parent as ViewableFolder).Node;
                lock (Node.Parent.Nodes)
                    Node.Parent.Nodes.Add(Node);
            }
        }

        protected override void LocalMove(UUID newParentUUID, InventoryFolder newParent)
        {
            Node oldParent = Node.Parent;
            lock (oldParent.Nodes)
                oldParent.Nodes.Remove(Node);
            base.LocalMove(newParentUUID, newParent);
            ViewableFolder parent = newParent as ViewableFolder;
            Node.Parent = parent.Node;
            lock (Node.Parent.Nodes)
                Node.Parent.Nodes.Add(Node);
            Inventory.NotifyParentChange(oldParent, Node.Parent, Node);
        }

        public override void Rename(string newName)
        {
            base.Rename(newName);
            Node.Text = newName;
            Inventory.NotifyNodeChanged(Node);
        }
    }

    public class ViewableFolder : InventoryFolder
    {
        public Node Node;
        private ViewableInventory Inventory;
        public ViewableFolder(InventoryManager manager, ViewableInventory inv, FolderData data)
            : base (manager, inv, data)
        {
            Node = new Node(this.Name);
            Node.Tag = this;
            Inventory = inv;
            if (Parent != null)
            {
                Node.Parent = (Parent as ViewableFolder).Node;
                lock (Node.Parent.Nodes)
                    Node.Parent.Nodes.Add(Node);
            }
        }

        protected override void LocalMove(UUID newParentUUID, InventoryFolder newParent)
        {
            Node oldParent = Node.Parent;
            lock (oldParent.Nodes)
                oldParent.Nodes.Remove(Node);
            base.LocalMove(newParentUUID, newParent);
            ViewableFolder parent = newParent as ViewableFolder;
            Node.Parent = parent.Node;
            lock (Node.Parent.Nodes)
                Node.Parent.Nodes.Add(Node);
            Inventory.NotifyParentChange(oldParent, Node.Parent, Node);
        }

        public override void Rename(string newName)
        {
            base.Rename(newName);
            Node.Text = newName;
            Inventory.NotifyNodeChanged(Node);
        }
    }
    #endregion Model

    public class InventoryViewer : ApplicationContext
    {
        // Fields
        private Dictionary<UUID, AssetTransferAction> AssetTransfers = new Dictionary<UUID, AssetTransferAction>();
        private GridClient Client = new GridClient();
        private Form mainWindow = new Form();

        // Methods
        public InventoryViewer(string first, string last, string password)
        {
            //this.Client.Self.OnInstantMessage += new MainAvatar.InstantMessageCallback(this.Self_OnInstantMessage);
            Client.Assets.OnAssetReceived += new AssetManager.AssetReceivedCallback(this.Assets_OnAssetReceived);
            ViewableInventory inventory = new ViewableInventory(Client.Inventory);
            Client.InventoryStore = inventory;

            TreeViewAdv view = new TreeViewAdv();
            view.Dock = DockStyle.Fill;
            view.LoadOnDemand = true;
            NodeTextBox textBox = new NodeTextBox();
            textBox.DataPropertyName = "Text";
            textBox.Parent = view;
            textBox.EditEnabled = false;
            view.NodeControls.Add(textBox);
            //ContextMenuStrip ItemMenu = new ContextMenuStrip();
            //ItemMenu.Items.Add(new ToolStripMenuItem("Get Info", null, new EventHandler(this.getInfo_Click)));
            //ItemMenu.Items.Add(new ToolStripMenuItem("Print Asset", null, new EventHandler(this.printAsset_Click)));
            //ItemMenu.Items.Add(new ToolStripMenuItem("Save Asset...", null, new EventHandler(this.saveAsset_Click)));
            //ItemMenu.Items.Add(new ToolStripMenuItem("Delete", null, new EventHandler(this.delete_Click)));
            //ContextMenuStrip FolderMenu = new ContextMenuStrip();
            //FolderMenu.Items.Add(new ToolStripMenuItem("Get Info", null, new EventHandler(this.getInfo_Click)));
            //FolderMenu.Items.Add(new ToolStripMenuItem("Delete", null, new EventHandler(this.delete_Click)));
            //FolderMenu.Items.Add(new ToolStripMenuItem("Empty", null, new EventHandler(this.empty_Click)));
            //ContextMenuStrip GeneralMenu = new ContextMenuStrip();
            //GeneralMenu.Items.Add(new ToolStripMenuItem("Get Info", null, new EventHandler(this.getInfo_Click)));
            //GeneralMenu.Items.Add(new ToolStripMenuItem("Delete", null, new EventHandler(this.delete_Click)));
            //this.inventoryView = new InventoryTreeView();
            //this.inventoryView.GeneralContextMenu = GeneralMenu;
            //this.inventoryView.FolderContextMenu = FolderMenu;
            //this.inventoryView.ItemContextMenu = ItemMenu;
            //this.inventoryView.Dock = DockStyle.Fill;

            this.mainWindow.Controls.Add(view);
            this.mainWindow.FormClosing += new FormClosingEventHandler(this.Form_FormClosing);
            this.mainWindow.Show();
            MainForm = mainWindow;

            LoginParams loginp = Client.Network.DefaultLoginParams(first, last, password, "InventoryViewer by Christopher Omega", "0.1");
            Client.Network.OnLogin +=
                delegate (LoginStatus status, string message) {
                    if (status == LoginStatus.Success)
                    {
                        Console.WriteLine("Login success: " + message);
                        view.Model = inventory;
                    }
                    else if (status == LoginStatus.Failed)
                    {
                        Console.WriteLine("Login failed: " + message);
                        Application.Exit();
                    }
                };
            Client.Network.BeginLogin(loginp);
        }

        private void Assets_OnAssetReceived(AssetDownload transfer, Asset asset)
        {
            AssetTransferAction action;
            if (this.AssetTransfers.TryGetValue(transfer.ID, out action))
            {
                if (asset != null)
                {
                    action(asset);
                }
                else
                {
                    Console.WriteLine("Asset transfer failed: {0}", transfer.Status);
                }
                this.AssetTransfers.Remove(transfer.ID);
            }
        }

        //#region Context Menu Handlers
        //private void delete_Click(object sender, EventArgs e)
        //{
        //    Console.WriteLine("Delete not implemented yet.");
        //}

        //private void empty_Click(object sender, EventArgs e)
        //{
        //    Console.WriteLine("Empty not implemented yet.");
        //}

        //private void getInfo_Click(object sender, EventArgs e)
        //{
        //    foreach (InventoryBase inv in this.inventoryView.SelectedInventory)
        //    {
        //        Console.WriteLine("{0}: {1} ({2})", (inv is InventoryFolder) ? "Folder" : "Item", inv.Name, inv.UUID);
        //        Console.WriteLine("\tOwner: {0}", inv.OwnerID);
        //        Console.WriteLine("\tParent: {0}", inv.ParentUUID);
        //        if (inv is InventoryItem)
        //        {
        //            InventoryItem item = inv as InventoryItem;
        //            Console.WriteLine("\tAsset Type: {0}", item.AssetType);
        //            Console.WriteLine("\tAsset UUID: {0}", item.AssetUUID);
        //            Console.WriteLine("\tCreation date: {0}", item.CreationDate);
        //            Console.WriteLine("\tCreator ID: {0}", item.CreatorID);
        //            Console.WriteLine("\tDescription: {0}", item.Description);
        //            Console.WriteLine("\tGroup ID: {0}", item.GroupID);
        //            Console.WriteLine("\tGroup owned: {0}", item.GroupOwned);
        //            Console.WriteLine("\tInventory Type: {0}", item.InventoryType);
        //            Console.WriteLine("\tPermissions: {0}", item.Permissions);
        //            Console.WriteLine("\tSale Type: {0}", item.SaleType);
        //            Console.WriteLine("\tSale Price: {0}", item.SalePrice);
        //        }
        //        else if (inv is InventoryFolder)
        //        {
        //            InventoryFolder folder = inv as InventoryFolder;
        //            Console.WriteLine("\tDescendants: {0}", folder.DescendentCount);
        //            Console.WriteLine("\tPrefered Type: {0}", folder.PreferredType);
        //            Console.WriteLine("\tVersion: {0}", folder.Version);
        //        }
        //        else
        //        {
        //            Console.WriteLine("Unknown inventory type {0}", inv.GetType());
        //        }
        //    }
        //}

        //private void printAsset_Click(object sender, EventArgs e)
        //{
        //    foreach (InventoryBase inv in this.inventoryView.SelectedInventory)
        //    {
        //        if (inv is InventoryItem)
        //        {
        //            InventoryItem item = inv as InventoryItem;
        //            LLUUID transferID = this.Client.Assets.RequestInventoryAsset(item.AssetUUID, item.UUID, LLUUID.Zero, item.OwnerID, item.AssetType, false);
        //            this.AssetTransfers.Add(transferID, new AssetTransferAction(this.PrintAsset));
        //        }
        //    }
        //}

        //private void saveAsset_Click(object sender, EventArgs e)
        //{
        //    foreach (InventoryBase inv in this.inventoryView.SelectedInventory)
        //    {
        //        if (inv is InventoryItem)
        //        {
        //            InventoryItem item = inv as InventoryItem;
        //            LLUUID transferID = this.Client.Assets.RequestInventoryAsset(item.AssetUUID, item.UUID, LLUUID.Zero, item.OwnerID, item.AssetType, false);
        //            this.AssetTransfers.Add(transferID, new AssetTransferAction(this.SaveAsset));
        //        }
        //    }
        //}
        //#endregion

        private delegate void AssetTransferAction(Asset asset);

        public void PrintAsset(Asset asset)
        {
            if (asset is AssetScriptText)
            {
                AssetScriptText script = asset as AssetScriptText;
                Console.WriteLine(script.Source);
            }
            else if (asset is AssetNotecard)
            {
                AssetNotecard note = asset as AssetNotecard;
                Console.WriteLine(note.Text);
            }
            else
            {
                Console.WriteLine("Unable to handle asset type {0}", asset.GetType());
            }
        }

        public void SaveAsset(Asset asset)
        {
            Console.WriteLine("SaveAsset not implemented yet!");
        }

        //private void Self_OnInstantMessage(LLUUID fromAgentID, string fromAgentName, LLUUID toAgentID, uint parentEstateID, LLUUID regionID, LLVector3 position, MainAvatar.InstantMessageDialog dialog, bool groupIM, LLUUID imSessionID, DateTime timestamp, string message, MainAvatar.InstantMessageOnline offline, byte[] binaryBucket, Simulator simulator)
        //{
        //    Console.WriteLine("IM ({0}): {1}", fromAgentName, message);
        //}

        public void Logout()
        {
            this.Client.Network.Logout();
            base.ExitThread();
        }

        private void Form_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Logout();
        }

        private static InventoryViewer Viewer;
        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            Viewer.Logout();
        }

        private static void Main(string[] args)
        {
            if (args.Length < 3)
            {
                Console.WriteLine("Usage: InventoryViewer first last password");
            }
            else
            {
                Console.CancelKeyPress += new ConsoleCancelEventHandler(InventoryViewer.Console_CancelKeyPress);
                Viewer = new InventoryViewer(args[0], args[1], args[2]);
                Application.Run(Viewer);
            }
        }
    }
}